﻿namespace Frameworks
{
    using System;
    using System.Diagnostics;
    using System.Text.RegularExpressions;

    [Serializable]
    internal class LogStackFrame
    {
        public string MethodName { get; private set; }
        public string DeclaringType { get; private set; }
        public string ParameterSig { get; private set; }
        public int LineNumber { get; private set; }
        public string FileName { get; private set; }

        public string FormattedMethodNameWithFileName { get; private set; }
        public string FormattedMethodName { get; private set; }
        public string FormattedFileName { get; private set; }

        public LogStackFrame(StackFrame frame)
        {
            var method = frame.GetMethod();
            MethodName = method.Name;
            DeclaringType = method.DeclaringType.FullName;

            var pars = method.GetParameters();
            for (int i = 0; i < pars.Length; i++)
            {
                ParameterSig += string.Format("{0} {1}", pars[i].ParameterType, pars[i].Name);
                if (i + 1 < pars.Length)
                {
                    ParameterSig += ", ";
                }
            }

            FileName = frame.GetFileName();
            LineNumber = frame.GetFileLineNumber();
            MakeFormattedNames();
        }

        public LogStackFrame(string unityStackFrame)
        {
            if (ExtractInfoFromUnityStackInfo(unityStackFrame))
            {
                MakeFormattedNames();
            }
            else
            {
                FormattedMethodNameWithFileName = unityStackFrame;
                FormattedMethodName = unityStackFrame;
                FormattedFileName = unityStackFrame;
            }
        }

        public LogStackFrame(string message, string filename, int lineNumber)
        {
            FileName = filename;
            LineNumber = lineNumber;
            FormattedMethodNameWithFileName = message;
            FormattedMethodName = message;
            FormattedFileName = message;
        }

        private bool ExtractInfoFromUnityStackInfo(string log)
        {
            var match = Regex.Matches(log, @"(.*)\.(.*)\s*\(.*\(at (.*):(\d+)");

            if (match.Count > 0)
            {
                DeclaringType = match[0].Groups[1].Value;
                MethodName = match[0].Groups[2].Value;
                FileName = match[0].Groups[3].Value;
                LineNumber = Convert.ToInt32(match[0].Groups[4].Value);
                return true;
            }
            return false;
        }

        private void MakeFormattedNames()
        {
            FormattedMethodName = string.Format("{0}.{1}({2})", DeclaringType, MethodName, ParameterSig);

            string filename = FileName;
            if (!string.IsNullOrEmpty(FileName))
            {
                var startSubName = FileName.IndexOf("Assets", StringComparison.OrdinalIgnoreCase);
                if (startSubName > 0)
                {
                    filename = FileName.Substring(startSubName);
                }
            }

            FormattedFileName = string.Format("{0}:{1}", filename, LineNumber);
            FormattedMethodNameWithFileName = string.Format("{0} (at {1})", FormattedMethodName, FormattedFileName);
        }
    }
}
